﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Sitecore.Data.Items;
using System.Data;
using Workflow.Alerts.DAL;
using System.Text;
using System.Globalization;
using Workflow.Alerts.Utils;
using workflow.Dal;

namespace Workflow.Alerts
{
    public class ExecuteViewPresenter : ActionPresenter
    {
        #region members
        private readonly IExecuteView view;
        private AlertViewDAL model;
        #endregion

        #region constructor
        public ExecuteViewPresenter(IExecuteView _view)
            : this(_view, null)
        { }

        public ExecuteViewPresenter(IExecuteView _view, ISessionProvider session)
            : base(_view, session)
        {
            view = base.GetView<IExecuteView>();
            view.ExecuteLoad += view_OnLoad;
            view.ExecuteSave += view_OnSave;
            model = new AlertViewDAL();

        }
        #endregion

        #region private methods

        private DataTable GetContractors(WorkflowFilterSql filterSql)
        {
            var contractors = model.GetContractors(filterSql);
            DataRow emptyContractor = contractors.NewRow();
            emptyContractor["id"] = 0;
            emptyContractor["name"] = "none";
            contractors.Rows.InsertAt(emptyContractor, 0);
            contractors.AcceptChanges();
            return contractors;
        }

        private void view_OnLoad()
        {
            WorkflowFilter filter = new WorkflowFilter()
            {
                AlertId = view.AlertId,
                MunicipalityId = alertDetails != null ? alertDetails.MunicipalityId : CurrentUser.TypeId
            };
            WorkflowFilterSql filterSql = new WorkflowFilterSql(filter);

            GetActualData(filterSql);

            view.AlertArea = alertDetails.ActualArea ?? alertDetails.EstimateArea;
            view.StartDate = alertDetails.ActualStartDate ?? alertDetails.EstimateStartDate;
            view.EndDate = alertDetails.ActualEndDate ?? alertDetails.EstimateEndDate;
            view.Comments = alertDetails.Comments;
            if (alertDetails.UseMunicipConstractor == 1)
            {
                view.ContractorList = GetContractors(filterSql);
                view.Contractor = alertDetails.ContractorId;
            }


        }

        private void GetActualData(WorkflowFilterSql filterSql)
        {
            if (alertDetails == null)
                alertDetails = new AlertDetails();

            EstateDataSet.ActualDataDataTable actualData = model.GetActualData(filterSql);
            if (actualData.Rows.Count == 1)
            {
                var row = actualData[0];
                if (!String.IsNullOrEmpty(row.actualarea))
                    alertDetails.ActualArea = Int32.Parse(row.actualarea);
                if (!String.IsNullOrEmpty(row.actualstartdate))
                    alertDetails.ActualStartDate = DateTime.Parse(row.actualstartdate, DateTimeFormatInfo.CurrentInfo);
                if (!String.IsNullOrEmpty(row.actualenddate))
                    alertDetails.ActualEndDate = DateTime.Parse(row.actualenddate, DateTimeFormatInfo.CurrentInfo);

                alertDetails.ContractorId = string.IsNullOrEmpty(row.contractorid) ? null : (Nullable<int>)Int32.Parse(row.contractorid);
                alertDetails.CurrentStatus = (WorkflowEnums.Status)row.currentstatus;
                alertDetails.UseMunicipConstractor = (row.usemunicipconstractor) ? 1 : 0;

                alertDetails.Comments = row.comments;

            }
        }

        private void view_OnSave()
        {
            using (WorkflowEntitySet context = new WorkflowEntitySet())
            {
                var listOfTempAlerts = TempChanges;
                Alert alert = listOfTempAlerts.Where(a => a.id == view.AlertId).FirstOrDefault();
                if (alert != null)
                    listOfTempAlerts.Remove(alert);
                alert = new Alert();
                alert.id = view.AlertId;
                alert.actualarea = view.AlertArea;
                alert.actualstartdate = view.StartDate;
                alert.actualenddate = view.EndDate;
                if (!string.IsNullOrEmpty(view.Comments))
                {
                    alert.Comments1.Add(new Comments()
                    {
                        comment = view.Comments,
                        createddatetime = DateTime.Now,
                        Person = context.Person.Where(p => p.id == CurrentUser.Id).First()
                    });
                }
                else
                {
                    var tempComment = alert.Comments1.Where(c => c.id == 0).FirstOrDefault();
                    if (tempComment != null)
                        alert.Comments1.Remove(tempComment);
                }

                if (view.Contractor.HasValue)
                {
                    alert.Contractor = context.Contractor.Where(c => c.id == view.Contractor.Value).First();
                }


                WorkflowEnums.Status? newstatus = null;
                switch (CurrentUser.Type)
                {
                    case WorkflowEnums.UserType.Municipality:
                        if (view.ChangeStatus)
                            newstatus = (view.IsPartiallyAccepted) ? WorkflowEnums.Status.AcceptedPartially :
                                                                 WorkflowEnums.Status.Accepted;
                        break;
                    case WorkflowEnums.UserType.NetworkOperator:
                        newstatus = (view.Contractor == 1) ? WorkflowEnums.Status.Executed4Contractor :
                                                             WorkflowEnums.Status.Executed4Municipality;
                        break;
                }

                alert.currentstatus = (int)newstatus;
                listOfTempAlerts.Add(alert);
                TempChanges = listOfTempAlerts;

                if (CurrentUser.Type == WorkflowEnums.UserType.NetworkOperator)
                {
                    SaveChangesToDB(alert);
                }
            }
        }

        private void SaveChangesToDB(Alert alert)
        {
            using (WorkflowEntitySet context = new WorkflowEntitySet())
            {

                var dbAlert = context.Alert.Include("AlertMaterials").Include("Comments1").Where(a => a.id == alert.id).First();
                dbAlert.actualarea = alert.actualarea;
                dbAlert.actualenddate = alert.actualenddate;
                dbAlert.actualstartdate = alert.actualstartdate;
                dbAlert.currentstatus = alert.currentstatus;

                if (alert.Contractor != null)
                {
                    dbAlert.Contractor = context.Contractor.Where(c => c.id == alert.Contractor.id).First();
                    dbAlert.contractorname = alert.Contractor.name;
                }
                else
                {
                    dbAlert.Contractor = null;
                    dbAlert.contractorname = string.Empty;
                }

                var comment = alert.Comments1.FirstOrDefault();
                if (comment != null && !string.IsNullOrEmpty(comment.comment))
                {
                    var comments = new Comments();
                    context.AddToComments(comments);
                    comments.Alert = dbAlert;
                    comments.comment = comment.comment;
                    comments.createddatetime = comment.createddatetime;
                    comments.Person = context.Person.Where(p => p.id == comment.Person.id).First();
                }

                List<AlertMaterials> listOfAlertMaterials = Session["TempAlertMaterials"] as List<AlertMaterials>;

                var alertMaterials = listOfAlertMaterials.Where(am => am.Alert.id == alert.id).ToList();
                //clear exiting materials
                var listofUsedMaterials = dbAlert.AlertMaterials.ToList();
                foreach (var am in listofUsedMaterials)
                {
                    context.DeleteObject(am);
                }
                dbAlert.AlertMaterials.Clear();

                foreach (var alerMaterial in alertMaterials)
                {
                    var dbAlertMaterial = new AlertMaterials();
                    dbAlertMaterial.Alert = dbAlert;
                    dbAlertMaterial.Materials = context.Materials.Where(m => m.id == alerMaterial.Materials.id).First();
                    dbAlertMaterial.price = alerMaterial.price;
                    dbAlertMaterial.quantity = alerMaterial.quantity;
                    dbAlertMaterial.uitstel = alerMaterial.uitstel;
                    dbAlertMaterial.uitvoerd = alerMaterial.uitvoerd;
                    context.AddToAlertMaterials(dbAlertMaterial);
                }

                AlertHistory ah = new AlertHistory();
                context.AddToAlertHistory(ah);
                ah.Alert = dbAlert;
                ah.date = DateTime.Now;
                ah.Person = context.Person.Where(p => p.id == CurrentUser.Id).First();
                ah.status = alert.currentstatus;

                context.SaveChanges();

            }
        }

        private void SendNotification(EstateDataSet.ContactAlertsRow contact, int status, string alertid)
        {
            if (CurrentUser.Type == WorkflowEnums.UserType.Municipality)
            {
                if ((WorkflowEnums.Status)status == WorkflowEnums.Status.Accepted || (WorkflowEnums.Status)status == WorkflowEnums.Status.AcceptedPartially)
                {
                    //save invoice data
                    WorkflowFilter filter = new WorkflowFilter()
                    {
                        AlertId = Int32.Parse(alertid)
                    };
                    AlertViewDAL dal = new AlertViewDAL();
                    dal.PrepareInvoiceData(new WorkflowFilterSql(filter));
                }

                if (contact != null && contact.nonotification)
                    Notification.SendNotification(alertid, status, contact);
            }
            else
            {
                if (contact != null &&
                    contact.munnotification &&
                    status != (Int32)WorkflowEnums.Status.Deleted &&
                    status != (Int32)WorkflowEnums.Status.Sent)
                    Notification.SendNotification(alertid, status, contact);
            }
        }

        #endregion

        #region Properties
        protected AlertDetails alertDetails
        {
            get
            {
                return Session[WorkflowConstants.ExecuteData] as AlertDetails;
            }
            set
            {
                Session[WorkflowConstants.ExecuteData] = value;
            }
        }
        #endregion
    }
}
